package com.demo.job.controller;

import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import io.github.resilience4j.retry.annotation.Retry;
import io.github.resilience4j.timelimiter.annotation.TimeLimiter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 熔断器测试控制器
 * 用于测试Resilience4j熔断器功能
 */
@RestController
@RequestMapping("/test")
@Slf4j
public class CircuitBreakerTestController {

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 测试调用订单服务
     */
    @GetMapping("/order")
    @CircuitBreaker(name = "order-service", fallbackMethod = "orderFallback")
    @Retry(name = "order-service")
    @TimeLimiter(name = "order-service")
    public CompletableFuture<String> testOrderService() {
        return CompletableFuture.supplyAsync(() -> {
            log.info("调用订单服务...");
            
            // 模拟随机失败
            if (ThreadLocalRandom.current().nextBoolean()) {
                throw new RuntimeException("模拟订单服务异常");
            }
            
            try {
                String result = restTemplate.getForObject("http://order-service/orders/test", String.class);
                log.info("订单服务调用成功: {}", result);
                return result;
            } catch (Exception e) {
                log.error("订单服务调用失败", e);
                throw new RuntimeException("订单服务调用失败: " + e.getMessage());
            }
        });
    }

    /**
     * 订单服务熔断降级方法
     */
    public CompletableFuture<String> orderFallback(Exception ex) {
        log.warn("订单服务熔断降级，原因: {}", ex.getMessage());
        return CompletableFuture.completedFuture("订单服务暂时不可用，请稍后重试");
    }

    /**
     * 批量测试接口
     */
    @GetMapping("/batch/{count}")
    public String batchTest(@PathVariable int count) {
        log.info("开始批量测试，次数: {}", count);
        
        int successCount = 0;
        int failureCount = 0;
        
        for (int i = 0; i < count; i++) {
            try {
                CompletableFuture<String> future = testOrderService();
                String result = future.get();
                if (!result.contains("暂时不可用")) {
                    successCount++;
                } else {
                    failureCount++;
                }
                log.info("第{}次调用结果: {}", i + 1, result);
            } catch (Exception e) {
                failureCount++;
                log.error("第{}次调用失败: {}", i + 1, e.getMessage());
            }
            
            // 间隔1秒
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                break;
            }
        }
        
        String result = String.format("批量测试完成 - 总次数: %d, 成功: %d, 失败: %d", 
                count, successCount, failureCount);
        log.info(result);
        return result;
    }

    /**
     * 强制触发异常测试
     */
    @GetMapping("/force-error")
    @CircuitBreaker(name = "order-service", fallbackMethod = "orderFallback")
    public CompletableFuture<String> forceError() {
        return CompletableFuture.supplyAsync(() -> {
            log.info("强制触发异常...");
            throw new RuntimeException("强制触发的测试异常");
        });
    }

    /**
     * 模拟超时测试
     */
    @GetMapping("/timeout")
    @CircuitBreaker(name = "order-service", fallbackMethod = "orderFallback")
    @TimeLimiter(name = "order-service")
    public CompletableFuture<String> timeoutTest() {
        return CompletableFuture.supplyAsync(() -> {
            log.info("模拟超时测试...");
            try {
                // 模拟长时间处理
                Thread.sleep(15000); // 15秒，超过配置的10秒超时
                return "处理完成";
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException("处理被中断");
            }
        });
    }

    /**
     * 健康检查接口
     */
    @GetMapping("/health")
    public String health() {
        return "Job服务健康状态正常";
    }
}